#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
将时间轴截图转换为动图
"""

from PIL import Image, ImageDraw, ImageFont
import os
import glob
import re
import io
import json


def create_timeline_gif(pattern="timeline_item_*.jpg", 
                        resize_ratio=0.5,  # 缩小比例（0.5 = 缩小到50%）
                        color_count=64,    # 颜色数量（越少文件越小）
                        quality_level=2):   # 质量等级：1=最小，2=平衡，3=最大
    """创建时间轴动图
    
    Args:
        pattern: 文件匹配模式
        resize_ratio: 图片缩小比例（0.5 = 缩小到50%）
        color_count: GIF颜色数量（32/64/128，越少文件越小）
        quality_level: 质量等级（1=最小文件，2=平衡，3=最大质量）
    """
    try:
        # 根据质量等级提供建议参数（仅在使用默认值时）
        # 注意：用户显式设置的参数会保留
        print(f"⚙️  质量等级: {quality_level} (1=最小，2=平衡，3=最大)")
        print(f"⚙️  用户设置: 缩放{resize_ratio}, 颜色{color_count}")
        
        # 如果是等级1或2，且用户设置超出建议值，给出警告但不强制修改
        if quality_level == 1 and (resize_ratio > 0.4 or color_count > 32):
            print(f"⚠️  提示: 等级1建议 缩放≤0.4, 颜色≤32 以获得最小文件")
        elif quality_level == 2 and (resize_ratio > 0.5 or color_count > 64):
            print(f"⚠️  提示: 等级2建议 缩放≤0.5, 颜色≤64 以保持平衡")
        
        # 应用用户设置（不再强制限制）
        # 设置截图目录
        screenshots_dir = "screenshots"
        
        # 查找所有时间轴截图
        timeline_pattern = os.path.join(screenshots_dir, pattern)
        all_files = glob.glob(timeline_pattern)
        
        if not all_files:
            print("✗ 未找到时间轴截图文件")
            return False
        
        # 过滤掉非时间轴截图（排除包含特定关键词的文件）
        # 注意：'optimized' 不在排除列表中，因为我们要支持使用优化后的图片
        exclude_keywords = ['initial', 'after', 'before', 'final', 'popup', 'positioning', 'timeline_item']
        timeline_files = []
        for file in all_files:
            filename = os.path.basename(file).lower()
            # 检查文件名是否包含排除关键词
            if not any(keyword in filename for keyword in exclude_keywords):
                timeline_files.append(file)
        
        print(f"📋 匹配到 {len(all_files)} 个文件，过滤后剩余 {len(timeline_files)} 个")
        
        if not timeline_files:
            print("✗ 未找到有效的时间轴截图文件")
            print("提示: 文件名应该是 {lng}-{lat}-{name}-{时间}.jpg 格式")
            return False
        
        # 按文件名排序（保持原有顺序）
        timeline_files.sort()
        
        print(f"✓ 找到 {len(timeline_files)} 个时间轴截图文件")
        
        # 从文件名中提取时间标注数据
        timeline_labels = []
        try:
            # 从每个文件名中提取时间标签
            # 文件名格式: 
            # - 原始: {lng}-{lat}-{name}-{date_text}.jpg
            #   例如: "117.2739-38.950776-大韩庄-1988-05.jpg" -> "1988-05"
            # - 优化: {lng}-{lat}-{name}-{date_text}-optimized.jpg
            #   例如: "117.2739-38.950776-大韩庄-1988-05-optimized.jpg" -> "1988-05"
            # - 简单: "timeline-1988-05.jpg" -> "1988-05"
            for file_path in timeline_files:
                filename = os.path.basename(file_path)
                # 去掉.jpg后缀
                name_without_ext = filename.rsplit('.', 1)[0]
                
                # 如果文件名包含 '-optimized'，先去掉这部分
                if name_without_ext.endswith('-optimized'):
                    name_without_ext = name_without_ext[:-10]  # 去掉 '-optimized'
                
                # 获取最后一个'-'后的部分作为时间标签
                parts = name_without_ext.split('-')
                if len(parts) >= 2:
                    # 取最后一个部分作为时间标签
                    date_label = parts[-1]
                    
                    # 检查是否是 YYYYMM 格式（6位数字），如果是则格式化为 YYYY-MM
                    if date_label.isdigit() and len(date_label) == 6:
                        # 例如: "198805" -> "1988-05"
                        date_label = f"{date_label[:4]}-{date_label[4:]}"
                    # 或者检查是否已经是 YYYY-MM 格式（倒数第二个是4位年份）
                    elif len(parts) >= 2 and parts[-2].isdigit() and len(parts[-2]) == 4 and len(date_label) == 2:
                        # 例如: parts = [..., "1988", "05"] -> "1988-05"
                        date_label = f"{parts[-2]}-{parts[-1]}"
                    
                    timeline_labels.append(date_label)
                else:
                    timeline_labels.append(name_without_ext)
            
            print(f"✓ 从文件名提取了 {len(timeline_labels)} 个时间标签")
                
        except Exception as e:
            print(f"⚠️ 从文件名提取时间标签失败: {e}")
            print("⚠️ 将使用默认时间标签（图片索引号）")
            # 使用图片索引号作为默认标签
            timeline_labels = [f"{i+1:02d}" for i in range(len(timeline_files))]
        
        # 打印文件和时间标签对应关系
        for file, label in zip(timeline_files, timeline_labels):
            print(f"  - {os.path.basename(file)} -> 时间标签: {label}")
        
        # 加载所有图片
        images = []
        for file_path in timeline_files:
            try:
                img = Image.open(file_path)
                images.append(img)
                print(f"✓ 加载图片: {os.path.basename(file_path)} ({img.size})")
            except Exception as e:
                print(f"✗ 加载图片失败 {file_path}: {e}")
                continue
        
        if not images:
            print("✗ 没有成功加载任何图片")
            return False
        
        # 确保所有图片尺寸一致（使用第一张图片的尺寸）
        original_size = images[0].size
        print(f"原始尺寸: {original_size}")
        
        # 应用缩放
        if resize_ratio != 1.0:
            new_width = int(original_size[0] * resize_ratio)
            new_height = int(original_size[1] * resize_ratio)
            target_size = (new_width, new_height)
            print(f"缩放比例: {resize_ratio} (缩放后: {target_size})")
        else:
            target_size = original_size
        
        # 调整所有图片尺寸
        resized_images = []
        for i, img in enumerate(images):
            if img.size != target_size:
                img = img.resize(target_size, Image.Resampling.LANCZOS)
                print(f"✓ 调整图片 {i+1} 尺寸: {img.size}")
            resized_images.append(img)
        
        # 裁剪边界（去除上下各200像素，左右各100像素）
        crop_top = 200
        crop_bottom = 200
        crop_left = 100
        crop_right = 100
        
        # 计算裁剪后的尺寸
        cropped_width = target_size[0] - crop_left - crop_right
        cropped_height = target_size[1] - crop_top - crop_bottom
        
        print(f"裁剪参数: 上{crop_top}px, 下{crop_bottom}px, 左{crop_left}px, 右{crop_right}px")
        print(f"裁剪后尺寸: {cropped_width} x {cropped_height}")
        
        # 裁剪所有图片
        cropped_images = []
        for i, img in enumerate(resized_images):
            cropped_img = img.crop((crop_left, crop_top, crop_left + cropped_width, crop_top + cropped_height))
            cropped_images.append(cropped_img)
            print(f"✓ 裁剪图片 {i+1}: {cropped_img.size}")
        
        # 添加时间标注到图片
        annotated_images = []
        for i, img in enumerate(cropped_images):
            # 创建图片副本
            annotated_img = img.copy()
            draw = ImageDraw.Draw(annotated_img)
            
            # 尝试加载中文字体
            font = None
            font_paths = [
                "C:/Windows/Fonts/msyh.ttc",  # 微软雅黑
                "C:/Windows/Fonts/simsun.ttc",  # 宋体
                "C:/Windows/Fonts/simhei.ttf",  # 黑体
                "C:/Windows/Fonts/simkai.ttf",   # 楷体
                "C:/Windows/Fonts/arial.ttf",   # Arial
                "arial.ttf"
            ]
            
            for font_path in font_paths:
                try:
                    font = ImageFont.truetype(font_path, 36)
                    print(f"✓ 成功加载字体: {font_path}")
                    break
                except:
                    continue
            
            if font is None:
                try:
                    font = ImageFont.load_default()
                    print("✓ 使用默认字体")
                except:
                    print("✗ 无法加载任何字体")
            
            # 获取时间标注文本
            if i < len(timeline_labels):
                label_text = timeline_labels[i]
            else:
                label_text = f"时间点 {i+1}"
            
            # 计算文本位置（右上角）
            if font:
                bbox = draw.textbbox((0, 0), label_text, font=font)
                text_width = bbox[2] - bbox[0]
                text_height = bbox[3] - bbox[1]
            else:
                text_width = len(label_text) * 10
                text_height = 20
            
            # 文本位置
            x = cropped_width - text_width - 20
            y = 20
            
            # 绘制背景矩形
            padding = 10
            bg_rect = [x - padding, y - padding, x + text_width + padding, y + text_height + padding]
            draw.rectangle(bg_rect, fill=(0, 0, 0, 180))  # 半透明黑色背景
            
            # 绘制文本
            draw.text((x, y), label_text, fill=(255, 255, 255), font=font)
            
            annotated_images.append(annotated_img)
            print(f"✓ 添加时间标注 {i+1}: {label_text}")
        
        # 优化图片以减小GIF文件大小
        print("正在优化图片以减小GIF文件大小...")
        
        optimized_images = []
        for i, img in enumerate(annotated_images):
            # 转换为P模式（调色板模式）以减少颜色数
            try:
                if img.mode != 'P':
                    # 先确保是RGB模式
                    if img.mode != 'RGB':
                        img = img.convert('RGB')
                    # 再转换为P模式（使用自适应调色板）
                    p_img = img.quantize(colors=color_count, method=Image.Quantize.MEDIANCUT)
                    optimized_images.append(p_img)
                    print(f"✓ 优化图片 {i+1}: {img.size} -> 调色板模式({color_count}色)")
                else:
                    optimized_images.append(img)
                    print(f"✓ 图片 {i+1}: {img.size} -> 调色板模式(128色)")
            except Exception as e:
                print(f"⚠️ 优化图片 {i+1} 失败: {e}，使用原图")
                # 如果转换失败，至少确保是RGB模式
                if img.mode != 'RGB':
                    img = img.convert('RGB')
                optimized_images.append(img)
        
        # --- 保存优化后的单帧图片 ---
        # 检查是否已经是优化后的图片（避免重复保存）
        is_already_optimized = len(timeline_files) > 0 and 'optimized' in os.path.basename(timeline_files[0]).lower()
        
        if not is_already_optimized:
            temp_debug_dir = os.path.join(screenshots_dir, "temp_optimized_frames")
            if not os.path.exists(temp_debug_dir):
                os.makedirs(temp_debug_dir)
            
            print(f"正在保存优化后的单帧图片到 {temp_debug_dir}...")
            
            for i, img in enumerate(optimized_images):
                # 使用时间标签命名优化后的图片
                if i < len(timeline_labels):
                    time_label = timeline_labels[i]
                else:
                    time_label = f"{i+1:02d}"
                
                # 从原始文件名中提取前缀（经纬度和名称）
                if i < len(timeline_files):
                    original_filename = os.path.basename(timeline_files[i])
                    # 去掉扩展名
                    # 例如: "117.49975-38.827043-大港-198805.jpg" -> "117.49975-38.827043-大港-198805"
                    name_without_ext = original_filename.rsplit('.', 1)[0]
                    parts = name_without_ext.split('-')
                    
                    # 重建前缀（去掉最后的时间部分）
                    # 最后一部分可能是 YYYYMM(6位) 或 MM(2位)
                    last_part = parts[-1]
                    if last_part.isdigit() and (len(last_part) == 6 or len(last_part) == 4):
                        # 是6位年月或4位年份，去掉最后一部分
                        prefix = '-'.join(parts[:-1])
                    elif len(parts) >= 2 and parts[-2].isdigit() and len(parts[-2]) == 4 and len(last_part) == 2:
                        # 是 YYYY-MM 格式，去掉最后两部分
                        prefix = '-'.join(parts[:-2])
                    else:
                        # 否则去掉最后一部分
                        prefix = '-'.join(parts[:-1]) if len(parts) > 1 else "optimized"
                    
                    # 保存时使用原始的时间标签格式（不重新格式化）
                    # time_label已经在上面被格式化为 YYYY-MM 了，但我们要用原始格式
                    original_time = parts[-1]
                    debug_filename = f"{prefix}-{original_time}-optimized.jpg"
                else:
                    debug_filename = f"optimized-{time_label}.jpg"
                
                debug_filepath = os.path.join(temp_debug_dir, debug_filename)
                
                # 压缩保存为JPEG格式
                # 先转换回RGB模式以便保存为JPEG
                if img.mode == 'P':
                    img_rgb = img.convert('RGB')
                else:
                    img_rgb = img
                
                # 保存为压缩的JPEG
                img_rgb.save(debug_filepath, format='JPEG', quality=75, optimize=True)
                
                file_size_kb = os.path.getsize(debug_filepath) / 1024
                print(f"  - 保存: {debug_filename} (尺寸: {img.size}, 大小: {file_size_kb:.1f}KB)")
            print("✓ 优化后的单帧图片保存完成")
        else:
            print("✓ 跳过保存优化图片（已使用优化后的图片作为输入）")
        # --- 调试步骤结束 ---

        # 验证所有图片尺寸
        sizes = [img.size for img in optimized_images]
        if len(set(sizes)) == 1:
            print(f"✅ 所有优化后的图片尺寸一致: {sizes[0]}")
        else:
            print(f"⚠️ 优化后的图片尺寸不一致: {set(sizes)}")
            # 如果尺寸不一致，强制重新调整到第一个优化图片的尺寸
            first_optimized_size = optimized_images[0].size
            print(f"强制将所有图片调整到第一帧尺寸: {first_optimized_size}")
            optimized_images = [img.resize(first_optimized_size, Image.Resampling.LANCZOS) for img in optimized_images]
            print(f"✅ 强制调整后所有图片尺寸一致: {optimized_images[0].size}")
        
        # 3. 减少帧数（如果帧数太多）
        if len(optimized_images) > 15:
            # 如果帧数超过15帧，每隔一帧取一帧
            step = len(optimized_images) // 15
            optimized_images = optimized_images[::step]
            print(f"✓ 减少帧数: {len(annotated_images)} -> {len(optimized_images)} 帧")
        
        # 计算每帧显示时间（每0.8秒切换一张图片）
        frame_duration = 800  # 0.8秒 = 800毫秒
        total_duration = frame_duration * len(optimized_images)
        print(f"每帧显示时间: {frame_duration} 毫秒 (0.8秒)")
        
        # 创建动图
        # 根据pattern生成输出文件名
        if "optimized" in pattern:
            # 使用优化图片：temp_optimized_frames/117.49975-38.827043-大港-*-optimized.jpg
            # -> 117.49975-38.827043-大港-timeline_animation_from_optimized.gif
            base_pattern = pattern.replace("temp_optimized_frames/", "").replace("-*-optimized.jpg", "")
            output_filename = f"{base_pattern}-timeline_animation_from_optimized.gif"
        else:
            # 使用原始截图：117.49975-38.827043-大港-*.jpg
            # -> 117.49975-38.827043-大港-timeline_animation_annotated.gif
            base_pattern = pattern.replace("-*.jpg", "").replace("*.jpg", "timeline_animation_annotated")
            if not base_pattern.endswith(".gif"):
                output_filename = f"{base_pattern}-timeline_animation_annotated.gif"
            else:
                output_filename = base_pattern
        
        output_path = os.path.join(screenshots_dir, output_filename)
        
        print(f"正在创建动图: {output_path}")
        
        # 优化GIF生成参数以减小文件大小
        try:
            # 确保第一帧是有效的图片
            first_frame = optimized_images[0]
            other_frames = optimized_images[1:]
            
            # 保存为GIF
            first_frame.save(
                output_path,
                format='GIF',  # 明确指定格式
                save_all=True,
                append_images=other_frames,
                duration=frame_duration,
                loop=0,  # 无限循环
                optimize=True,
                # 添加更多优化参数
                disposal=2    # 帧处理方式
            )
        except Exception as e:
            print(f"⚠️ 使用高级参数保存失败: {e}")
            print("尝试使用基本参数保存...")
            # 如果高级参数失败，尝试基本参数
            optimized_images[0].save(
                output_path,
                format='GIF',
                save_all=True,
                append_images=optimized_images[1:],
                duration=frame_duration,
                loop=0
            )
        
        # 检查最终动图文件大小
        gif_size_kb = os.path.getsize(output_path) / 1024
        gif_size_mb = gif_size_kb / 1024
        
        print(f"✅ 动图创建成功: {output_path}")
        print(f"📊 动图信息:")
        print(f"  - 总帧数: {len(optimized_images)}")
        print(f"  - 每帧时长: {frame_duration} 毫秒")
        print(f"  - 总时长: {total_duration} 毫秒 ({total_duration/1000:.1f}秒)")
        print(f"  - 循环: 无限循环")
        print(f"  - 原始尺寸: {original_size}")
        print(f"  - 缩放比例: {resize_ratio}")
        print(f"  - 裁剪后尺寸: {cropped_width} x {cropped_height}")
        print(f"  - 颜色数: {color_count}")
        print(f"  - 时间标注: 已添加")
        if gif_size_mb >= 1:
            print(f"  - 最终大小: {gif_size_mb:.2f}MB ({gif_size_kb:.0f}KB)")
        else:
            print(f"  - 最终大小: {gif_size_kb:.1f}KB")
        
        return True
        
    except Exception as e:
        print(f"✗ 创建动图失败: {e}")
        return False

def main():
    """主函数"""
    print("=== 时间轴截图转动图 ===")
    
    if create_timeline_gif():
        print("\n✅ 动图创建完成！")
    else:
        print("\n✗ 动图创建失败！")

if __name__ == "__main__":
    main()
